package com.demo.oauth2jFinalShiroClient.util;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CacheMap<K, V> {
	// 这里使用ConcurrentHashMap避免，clean的时候，主线程修改chache，造成异常，
	// 使用ConcurrentHashMap可以控制并发修改cache
	private Map<K, ValueWithTTL<V>> cache = new ConcurrentHashMap<K, ValueWithTTL<V>>();
	private static boolean cleanTaskIsRunning = false;

	/**
	 * @param key
	 * @param value
	 * @param ttl(单位：秒)
	 */
	public void put(K key, V value, int ttl) {
		long expireTime = System.currentTimeMillis() + ttl * 1000;
		ValueWithTTL<V> valueWithTTL = new ValueWithTTL<>(expireTime, value);
		cache.put(key, valueWithTTL);
		if (!cleanTaskIsRunning) {
			startCleanTask();
			cleanTaskIsRunning = !cleanTaskIsRunning;
		}
	}

	public V get(K key) {
		ValueWithTTL<V> valueWithTTL = cache.get(key);
		return null == valueWithTTL ? null : valueWithTTL.getValue();
	}

	/**
	 * 启动清理线程
	 */
	private void startCleanTask() {
		Thread cleanThread = new Thread(new CleanTask());
		cleanThread.start();
	}

	/**
	 * 清理过期的key
	 */
	class CleanTask implements Runnable {
		public void run() {
			while (true) {
				long currentTime = System.currentTimeMillis();
				// 遍历map
				for (Map.Entry<K, ValueWithTTL<V>> entry : cache.entrySet()) {
					ValueWithTTL<V> valueWithTTL = entry.getValue();
					Long expireTime = valueWithTTL.getExpireIn();
					// 过期时间到了
					if (currentTime > expireTime) {
						cache.remove(entry.getKey());
					} // if
				} // for
				// 每隔1s扫描map对象
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} // while
		}
	}
}